﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Remoting;

using System.Threading;

namespace iLangl.StateMachine
{
	public class BaseStateMachine : BaseManager, IStateMachine
	{
		protected dtoMachineStatesDescriptor StatesDescriptor;

		public BaseStateMachine()
		{
			StatesDescriptor = new dtoMachineStatesDescriptor();

			if(StateMachineConfiguration.Instance != null)
				StatesDescriptor.ReadXml(StateMachineConfiguration.Instance.StateMachineFileName);
		}

		public BaseStateMachine(String StateMachineDescriptorFileName)
		{
			if (String.IsNullOrEmpty(StateMachineDescriptorFileName))
			{
				throw new NullReferenceException("FileName not specified!");
			}

			if (!File.Exists(StateMachineDescriptorFileName))
			{
				throw new FileNotFoundException(String.Format("'{0}' not found!"));
			}

			StatesDescriptor = new dtoMachineStatesDescriptor();

			StatesDescriptor.ReadXml(StateMachineDescriptorFileName);
		}

		private IActionDescriptor _descriptor;
		public void InitateNewProcess(IActionDescriptor descriptor)
		{
			_descriptor = descriptor;
			
			if (isMultyThreading)
			{
				Thread newProcess = new Thread(initateNewProcess);
				newProcess.Start();
			}
			else
			{
				initateNewProcess();
			}
		}

		private void initateNewProcess()
		{
			dtoMachineStatesDescriptor.StateRow state = StatesDescriptor.State.FindByVersionId(_descriptor.Version, _descriptor.ActionName);

			if (state == null)
			{
				throw new ExceptionActionNotFound(_descriptor.ActionName, _descriptor.Version);
			}

			IAction action;
			foreach (dtoMachineStatesDescriptor.ActionRow ar in state.GetActionRows())
			{
				try
				{
					ObjectHandle marshaled_plugin = (ObjectHandle)Activator.CreateInstance(ar.AssemblyName, ar.TypeName);
					action = (IAction)marshaled_plugin.Unwrap();
				

				action.SetActionDescriptor(_descriptor);
				action.ResponseContext.SetContext(_descriptor.ResponseContext.GetContext());
				action.Execute();
				
				}
				catch (System.Exception ex)
				{
					throw ex;
				}
			}
		}

		#region IStateMachine Members

		public void SetMutlyThreading(bool flag)
		{
			isMultyThreading = flag;
		}

		private bool isMultyThreading = true;
		public bool IsMultyThreading
		{
			get { return isMultyThreading; }
		}

		#endregion
	}	
}
